﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using OpenCvSharp;
using System;
using VIA.Integration;
using VIA.Integration.Alarms;
using VIA.Integration.Domain;
using VIA.Integration.LeadShine;
using VIA.Project.Domain.Services;
using VIA.SiMoJi.Domain.Electronics;
using VIA.SiMoJi.Domain.Option;
using VNetDxf.Entities;

namespace VIA.SiMoJi.Domain.Inspection
{
    public class SiMoStation : StationBase<SiMoStationOption>, ISuportClearAlarm
    {
        #region 字段
        public volatile BanYunStation BanYunStation;
        public volatile Feeder FeiDaStation1;
        public volatile Feeder FeiDaStation2;
        public volatile SiMoRunniningStatus Status;
        private bool jawSensorError;
        private bool jawPositionError;
        private bool xOffsetLimitError;
        private InspectorOption _inspectorOption;
        private bool _isInitialized;
        #endregion

        #region 运动位置
        private const string Jaw_安全位 = "安全位";
        private const string Jaw_夹膜等待位1 = "夹膜等待位1";
        private const string Jaw_夹膜等待位2 = "夹膜等待位2";
        private const string Jaw_夹膜位1 = "夹膜位1";
        private const string Jaw_夹膜位2 = "夹膜位2";
        private const string Jaw_撕膜结束位1 = "撕膜结束位1";
        private const string Jaw_撕膜结束位2 = "撕膜结束位2";
        private const string Jaw_撕膜过渡位1 = "撕膜过渡位1";
        private const string Jaw_撕膜过渡位2 = "撕膜过渡位2";
        private const string Jaw_抛膜位1 = "抛膜位1";
        private const string Jaw_抛膜位2 = "抛膜位2";

        private const string Ds_安全位 = "安全位";
        private const string Ds_夹膜位 = "夹膜位";
        private const string Ds_撕膜结束位 = "撕膜结束位";
        private const string Ds_撕膜过渡位 = "撕膜过渡位";
        private const string Ds_抛膜上1 = "抛膜上1";
        private const string Ds_抛膜下1 = "抛膜下1";
        private const string Ds_抛膜上2 = "抛膜上2";
        private const string Ds_抛膜下2 = "抛膜下2";
        #endregion

        #region 事件
        public event EventHandler<string> StepsChanged;
        #endregion

        #region 设备报警
        [Alarm(true, AlarmLevel.Error, "夹爪上光纤报警", Logical.Equal)]
        public bool JawSensorError
        {
            get => jawSensorError;
            set => NotifyAlarm(ref jawSensorError, value);
        }
        [Alarm(true, AlarmLevel.Error, "夹爪X轴纠偏量超上限", Logical.Equal)]
        public bool XOffsetLimitError
        {
            get => xOffsetLimitError;
            set => NotifyAlarm(ref xOffsetLimitError, value);
        }
        [Alarm(true, AlarmLevel.Error, "夹爪位置不正确报警", Logical.Equal)]
        public bool JawPositionError
        {
            get => jawPositionError;
            set => NotifyAlarm(ref jawPositionError, value);
        }
        #endregion

        #region 硬件设备
        [MotionPath(Ds_安全位)]
        [MotionPath(Ds_夹膜位)]
        [MotionPath(Ds_撕膜结束位)]
        [MotionPath(Ds_撕膜过渡位)]
        [MotionPath(Ds_抛膜上1)]
        [MotionPath(Ds_抛膜下1)]
        [MotionPath(Ds_抛膜上2)]
        [MotionPath(Ds_抛膜下2)]
        public DmcAxis DingSheng_Axis { get; private set; }

        [MotionPath(Jaw_安全位)]
        [MotionPath(Jaw_夹膜等待位1)]
        [MotionPath(Jaw_夹膜等待位2)]
        [MotionPath(Jaw_夹膜位1)]
        [MotionPath(Jaw_夹膜位2)]
        [MotionPath(Jaw_撕膜结束位1)]
        [MotionPath(Jaw_撕膜结束位2)]
        [MotionPath(Jaw_撕膜过渡位1)]
        [MotionPath(Jaw_撕膜过渡位2)]
        [MotionPath(Jaw_抛膜位1)]
        [MotionPath(Jaw_抛膜位2)]
        public DmcAxis Jaw1_Axis { get; private set; }
        [MotionPath(Jaw_安全位)]
        [MotionPath(Jaw_夹膜等待位1)]
        [MotionPath(Jaw_夹膜等待位2)]
        [MotionPath(Jaw_夹膜位1)]
        [MotionPath(Jaw_夹膜位2)]
        [MotionPath(Jaw_撕膜结束位1)]
        [MotionPath(Jaw_撕膜结束位2)]
        [MotionPath(Jaw_撕膜过渡位1)]
        [MotionPath(Jaw_撕膜过渡位2)]
        [MotionPath(Jaw_抛膜位1)]
        [MotionPath(Jaw_抛膜位2)]
        public DmcAxis Jaw2_Axis { get; private set; }
        [MotionPath(Jaw_安全位)]
        [MotionPath(Jaw_夹膜等待位1)]
        [MotionPath(Jaw_夹膜等待位2)]
        [MotionPath(Jaw_夹膜位1)]
        [MotionPath(Jaw_夹膜位2)]
        [MotionPath(Jaw_撕膜结束位1)]
        [MotionPath(Jaw_撕膜结束位2)]
        [MotionPath(Jaw_撕膜过渡位1)]
        [MotionPath(Jaw_撕膜过渡位2)]
        [MotionPath(Jaw_抛膜位1)]
        [MotionPath(Jaw_抛膜位2)]
        public DmcAxis Jaw3_Axis { get; private set; }
        [MotionPath(Jaw_安全位)]
        [MotionPath(Jaw_夹膜等待位1)]
        [MotionPath(Jaw_夹膜等待位2)]
        [MotionPath(Jaw_夹膜位1)]
        [MotionPath(Jaw_夹膜位2)]
        [MotionPath(Jaw_撕膜结束位1)]
        [MotionPath(Jaw_撕膜结束位2)]
        [MotionPath(Jaw_撕膜过渡位1)]
        [MotionPath(Jaw_撕膜过渡位2)]
        [MotionPath(Jaw_抛膜位1)]
        [MotionPath(Jaw_抛膜位2)]
        public DmcAxis Jaw4_Axis { get; private set; }
        [MotionPath(Jaw_安全位)]
        [MotionPath(Jaw_夹膜等待位1)]
        [MotionPath(Jaw_夹膜等待位2)]
        [MotionPath(Jaw_夹膜位1)]
        [MotionPath(Jaw_夹膜位2)]
        [MotionPath(Jaw_撕膜结束位1)]
        [MotionPath(Jaw_撕膜结束位2)]
        [MotionPath(Jaw_撕膜过渡位1)]
        [MotionPath(Jaw_撕膜过渡位2)]
        [MotionPath(Jaw_抛膜位1)]
        [MotionPath(Jaw_抛膜位2)]
        public DmcAxis Jaw5_Axis { get; private set; }
        [MotionPath(Jaw_安全位)]
        [MotionPath(Jaw_夹膜等待位1)]
        [MotionPath(Jaw_夹膜等待位2)]
        [MotionPath(Jaw_夹膜位1)]
        [MotionPath(Jaw_夹膜位2)]
        [MotionPath(Jaw_撕膜结束位1)]
        [MotionPath(Jaw_撕膜结束位2)]
        [MotionPath(Jaw_撕膜过渡位1)]
        [MotionPath(Jaw_撕膜过渡位2)]
        [MotionPath(Jaw_抛膜位1)]
        [MotionPath(Jaw_抛膜位2)]
        public DmcAxis Jaw6_Axis { get; private set; }
        [MotionPath(Jaw_安全位)]
        [MotionPath(Jaw_夹膜等待位1)]
        [MotionPath(Jaw_夹膜等待位2)]
        [MotionPath(Jaw_夹膜位1)]
        [MotionPath(Jaw_夹膜位2)]
        [MotionPath(Jaw_撕膜结束位1)]
        [MotionPath(Jaw_撕膜结束位2)]
        [MotionPath(Jaw_撕膜过渡位1)]
        [MotionPath(Jaw_撕膜过渡位2)]
        [MotionPath(Jaw_抛膜位1)]
        [MotionPath(Jaw_抛膜位2)]
        public DmcAxis Jaw7_Axis { get; private set; }

        public Electronic Electronic => Electronic.Default;
        public CylinderEx Jaw1_Cylinder { get => Electronic.Cylinder_夹爪1气缸; }
        public CylinderEx Jaw2_Cylinder { get => Electronic.Cylinder_夹爪2气缸; }
        public CylinderEx Jaw3_Cylinder { get => Electronic.Cylinder_夹爪3气缸; }
        public CylinderEx Jaw4_Cylinder { get => Electronic.Cylinder_夹爪4气缸; }
        public CylinderEx Jaw5_Cylinder { get => Electronic.Cylinder_夹爪5气缸; }
        public CylinderEx Jaw6_Cylinder { get => Electronic.Cylinder_夹爪6气缸; }
        public CylinderEx Jaw7_Cylinder { get => Electronic.Cylinder_夹爪7气缸; }
        public CylinderEx YaMo1_Cylinder { get => Electronic.Cylinder_飞达1压膜气缸; }
        public CylinderEx YaMo2_Cylinder { get => Electronic.Cylinder_飞达2压膜气缸; }
        public Feeder Feeder1 { get; }
        public Feeder Feeder2 { get; }
        public List<DmcAxis> JawAxises => [Jaw1_Axis, Jaw2_Axis, Jaw3_Axis, Jaw4_Axis, Jaw5_Axis, Jaw6_Axis, Jaw7_Axis];
        public List<CylinderEx> Cylinders => [Jaw1_Cylinder, Jaw2_Cylinder, Jaw3_Cylinder, Jaw4_Cylinder, Jaw5_Cylinder, Jaw6_Cylinder, Jaw7_Cylinder];
        public CardIoPoint[] JawSensors1 => [Electronic.DI65_夹爪膜检测光纤11, Electronic.DI66_夹爪膜检测光纤12, Electronic.DI67_夹爪膜检测光纤13, Electronic.DI68_夹爪膜检测光纤14, Electronic.DI69_夹爪膜检测光纤15, Electronic.DI70_夹爪膜检测光纤16, Electronic.DI71_夹爪膜检测光纤17];
        public CardIoPoint[] JawSensors2 => [Electronic.DI72_夹爪膜检测光纤21, Electronic.DI73_夹爪膜检测光纤22, Electronic.DI74_夹爪膜检测光纤23, Electronic.DI75_夹爪膜检测光纤24, Electronic.DI76_夹爪膜检测光纤25, Electronic.DI77_夹爪膜检测光纤26, Electronic.DI78_夹爪膜检测光纤27];

        #endregion

        #region 构造函数
        public SiMoStation(Feeder feeder1, Feeder feeder2)
        {
            RetryCount = 0;
            this.InitalizeAlarms();
            Feeder1 = feeder1;
            Feeder2 = feeder2;
            Feeder1.StepCountChanged += Feeder1_StepCountChanged;
            Feeder2.StepCountChanged += Feeder2_StepCountChanged;
            LogGroup = LoggerCategory.RunningInfo;
            DingSheng_Axis = new DmcAxis(Electronic.Controller) { Id = "SiMo" + nameof(DingSheng_Axis), NoId = 31, Name = "撕膜顶升步进" };
            Jaw1_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw1_Axis), NoId = 22, Name = "撕膜夹爪1步进" };
            Jaw2_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw2_Axis), NoId = 23, Name = "撕膜夹爪2步进" };
            Jaw3_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw3_Axis), NoId = 24, Name = "撕膜夹爪3步进" };
            Jaw4_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw4_Axis), NoId = 25, Name = "撕膜夹爪4步进" };
            Jaw5_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw5_Axis), NoId = 26, Name = "撕膜夹爪5步进" };
            Jaw6_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw6_Axis), NoId = 27, Name = "撕膜夹爪6步进" };
            Jaw7_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw7_Axis), NoId = 28, Name = "撕膜夹爪7步进" };
            Add(DingSheng_Axis);
            Add(Jaw1_Axis, Jaw2_Axis, Jaw3_Axis, Jaw4_Axis, Jaw5_Axis, Jaw6_Axis, Jaw7_Axis);
            Add(Feeder1.Axis, Feeder2.Axis);
            Add(Jaw1_Cylinder, Jaw2_Cylinder, Jaw3_Cylinder, Jaw4_Cylinder, Jaw5_Cylinder, Jaw6_Cylinder, Jaw7_Cylinder);
        }
        #endregion

        #region 初始流程
        public bool IsInitialized => _isInitialized;
        public async Task<bool> InitializeStation(CancellationToken cancellationToken)
        {
            try
            {
                OnStepChanged("初始化中");
                _isInitialized = false;
                LogInfo("初始化->[开始]");
                YaMo1_Cylinder.TakeBack();//张开
                YaMo2_Cylinder.TakeBack();//张开
                LogInfo("初始化->[飞达压膜气缸张开]");
                var axies = GetAxes();
                axies.ForEach(x => x.Reset());
                axies.ForEach(x => x.ServoOn(true));
                if (Step == SiMoStationRunStep.Step07_夹膜动作_气缸夹紧)
                {
                    LogInfo("初始化->[Step07][夹爪张开开始]");
                    await Parallel.ForEachAsync(Cylinders, cancellationToken, async (x, t) => await x.PushOutAsync());//先张开气缸
                    await Task.Delay(1000, cancellationToken);
                    await Judger.Sure(() => BanYunStation.IsInitialized, cancellationToken);
                    LogInfo("初始化->[Step07][夹爪张开结束]");
                }
                LogInfo("初始化->[夹爪闭合]");
                await Parallel.ForEachAsync(Cylinders, cancellationToken, async (x, t) => await x.TakeBackAsync());
                LogInfo("初始化->[顶升轴回原]");
                await DingSheng_Axis.MoveOriginAsync(cancellationToken);
                LogInfo("初始化->[顶升轴到安全位置]");
                await DingSheng_Axis.MoveToAsync(Ds_安全位, cancellationToken);
                LogInfo("初始化->[撕膜夹爪轴回原点]");
                await Parallel.ForEachAsync(JawAxises, cancellationToken, async (x, t) => await x.MoveOriginAsync(t));
                LogInfo("初始化->[撕膜夹爪轴到安全位置]");
                await JawAxises.MoveToAsync(Jaw_安全位, cancellationToken);
                if (Status.HasProducts.Any(x => x))
                {
                    Step = SiMoStationRunStep.Step01_获取撕膜位;
                }
                else
                {
                    Step = SiMoStationRunStep.Step01_获取撕膜位;
                }
                OnStepChanged("初始化完成");
                _isInitialized = true;

            }
            catch (Exception ex)
            {
                _isInitialized = false;
                OnStepChanged("初始化失败");
                LogError($"初始化->[异常]{ex.Message}", ex);
            }
            return _isInitialized;
        }
        #endregion

        #region 运行流程
        public SiMoStationRunStep Step
        {
            get => (SiMoStationRunStep)Status.Step;
            set
            {
                Status.Step = (int)value;
                Status.Save();
            }
        }
        /// <summary>
        /// 撕膜速度
        /// </summary>
        VelocityCurve SiMoVelocityCurve => new VelocityCurve() { Maxvel = _inspectorOption.SiMoSpeed, Tdec = 0.1, Tacc = 0.1 };
        SiMoMotionTimeOption motionTimeOption => _inspectorOption.SMMotionTimeOption;
        protected override async Task PreRunning()
        {
            try
            {
                var axisList = GetAxes();
                foreach (var axis in axisList)
                {
                    await axis.InitializeAsync();
                }
                _inspectorOption = _optionRepository.Get<InspectorOption>();
                Status = RunningStatus.GetRecord<SiMoRunniningStatus>("SiMoStation.json");
                Option = Recipe.Get<SiMoStationOption>(Id);
                if (_isInitialized == false)
                {
                    throw new Exception("未初始化");
                }
                else
                {
                    for (int i = 0; i < JawAxises.Count; i++)
                    {
                        if (Math.Abs(JawAxises[i].Current - Status.JaxAxisesPositions[i]) > 1)//用于检查当前状态是否一致
                        {
                            await JawAxises[i].MoveToAsync(Jaw_安全位, CancellationToken);
                        }
                    }
                }
                await RecoverPreRunning();
            }
            catch (Exception ex)
            {
                Root.Stop();
                LogError($"运行之前异常", ex);
            }
        }
        protected override async Task RunningCoreAsync()
        {
            await Step01_获取撕膜位();
            await Step02_顶升夹膜位();
            await Step03_等待搬运完成();
            await Step04_夹膜动作_Z轴顶升();
            await Step05_夹膜动作_气缸张开();
            await Step06_夹膜动作_夹爪_夹膜位();
            await Step07_夹膜动作_气缸夹紧();
            await Step08_撕膜动作_过渡位();
            await Step09_撕膜动作_夹爪_结束位();
            await Step10_撕膜动作_顶升_结束位();
            await Step11_抛膜动作_顶升_抛膜上();
            await Step12_抛膜动作_夹爪_抛膜位();
            await Step13_抛膜动作_顶升_抛膜下();
            await Step14_抛膜动作_夹爪_等待位();
        }
        protected override async void OnStopped()
        {
            var axies = GetAxes();
            await Parallel.ForEachAsync(axies, cancellationToken: default, async (x, t) => await x.PauseAsync());
            SaveRuningRecordState();
        }
        async Task Step01_获取撕膜位()
        {
            if (Step != SiMoStationRunStep.Step01_获取撕膜位) return;
            OnStepChanged("Step01_获取撕膜位");
            LogInfo($"Step01_获取撕膜位->[开始]");
            await Judger.Sure(() => FeiDaStation1.CheckIsReady() || FeiDaStation2.CheckIsReady(), CancellationToken, interval: 200);
            if (FeiDaStation1.CheckIsReady())
            {
                SignalPanel.Signal.IsUseSiMo1 = true;
                SignalPanel.Signal.SiMoReady = true;
                LogInfo("Step01_获取撕膜位->[飞达1已经就绪]");
            }
            else
            {
                SignalPanel.Signal.IsUseSiMo1 = false;
                SignalPanel.Signal.SiMoReady = true;
                LogInfo("Step01_获取撕膜位->[飞达2已经就绪]");
            }
            SignalPanel.Signal.FeedrReadyDone = true;
            await Judger.Sure(() => SignalPanel.Signal.FeedrNotReady == false);
            SignalPanel.Signal.FeedrReadyDone = false;
            LogInfo("Step01_获取撕膜位->[夹爪移动到夹膜等待位]");
            string ps = SignalPanel.Signal.IsUseSiMo1 ? Jaw_夹膜等待位1 : Jaw_夹膜等待位2;
            await JawAxises.MoveToAsync(ps, CancellationToken);
            await CheckCancellationToken();
            LogInfo("Step01_获取撕膜位->[结束]");
            Step = SiMoStationRunStep.Step02_顶升夹膜位;
        }
        async Task Step02_顶升夹膜位()
        {
            if (Step != SiMoStationRunStep.Step02_顶升夹膜位) return;
            OnStepChanged("Step02_顶升夹膜位");
            LogInfo($"Step02_顶升夹膜位->[开始]");
            await DingSheng_Axis.MoveToAsync(Ds_夹膜位, CancellationToken);
            await CheckCancellationToken();
            Step = SiMoStationRunStep.Step03_等待搬运完成;
            LogInfo($"Step02_顶升夹膜位->[结束]");
        }
        async Task Step03_等待搬运完成()
        {
            if (Step != SiMoStationRunStep.Step03_等待搬运完成) return;
            OnStepChanged("Step03_等待搬运完成");
            LogInfo($"Step03_等待搬运完成->[开始]");
            await Judger.Sure(() => SignalPanel.Signal.BanYunCompleted || SignalPanel.Signal.FeedrNotReady, CancellationToken);
            if (SignalPanel.Signal.FeedrNotReady)
            {
                LogInfo($"Step03_等待搬运完成->[跳回Step01_获取撕膜位]");
                Step = SiMoStationRunStep.Step01_获取撕膜位;//跳回之前第[Step01_获取撕膜位]步重新确认是用那个飞达功能
                return;
            }
            Step = SiMoStationRunStep.Step04_夹膜动作_Z轴顶升;
            LogInfo($"Step03_等待搬运完成->[结束]");
        }
        async Task Step04_夹膜动作_Z轴顶升()
        {
            if (Step != SiMoStationRunStep.Step04_夹膜动作_Z轴顶升) return;
            OnStepChanged("Step04_夹膜动作_Z轴顶升");
            LogInfo($"Step04_夹膜动作_Z轴顶升->[开始]");
            if (!DingSheng_Axis.CheckIsInPosition(Ds_夹膜位))
                await DingSheng_Axis.MoveToAsync(Ds_夹膜位, CancellationToken);
            await CheckCancellationToken();
            LogInfo($"Step04_夹膜动作_Z轴顶升->[结束]");
            Step = SiMoStationRunStep.Step05_夹膜动作_气缸张开;
        }
        async Task Step05_夹膜动作_气缸张开()
        {
            if (Step != SiMoStationRunStep.Step05_夹膜动作_气缸张开) return;
            OnStepChanged("Step05_夹膜动作_气缸张开");
            LogInfo($"Step05_夹膜动作_气缸张开->[开始]");
            foreach (var item in Cylinders)
            {
                item.PushOut();
            }
            await Task.Delay(motionTimeOption.JiaMoCylinderPushOutDelay, CancellationToken);
            LogInfo($"Step05_夹膜动作_气缸张开->[结束]");
            Step = SiMoStationRunStep.Step06_夹膜动作_夹爪_夹膜位;
        }
        async Task Step06_夹膜动作_夹爪_夹膜位()
        {
            if (Step != SiMoStationRunStep.Step06_夹膜动作_夹爪_夹膜位) return;
            OnStepChanged("Step06_夹膜动作_夹爪_夹膜位");
            LogInfo($"Step06_夹膜动作_夹爪_夹膜位->[开始]");
            string position = SignalPanel.Signal.IsUseSiMo1 ? Jaw_夹膜位1 : Jaw_夹膜位2;
            double tolerance = 5;
            if (SignalPanel.Signal.JawOffsets.Any(x => Math.Abs(x) > tolerance))
            {
                XOffsetLimitError = true;
                LogError($"Step06_夹膜动作_夹爪_夹膜位->[夹爪X轴纠偏量超上限5mm:{tolerance}]!");
                await Task.Delay(1000);
                return;
            }
            var p1 = Jaw1_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[0];
            var p2 = Jaw2_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[1];
            var p3 = Jaw3_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[2];
            var p4 = Jaw4_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[3];
            var p5 = Jaw5_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[4];
            var p6 = Jaw6_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[5];
            var p7 = Jaw7_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[6];
            var targetList = new List<double>() { p1, p2, p3, p3, p4, p5, p6, p7 };
            var offsetList = SignalPanel.Signal.JawOffsets;
            targetList = targetList.Select(x => Math.Round(x, 2)).ToList();
            offsetList = offsetList.Select(x => Math.Round(x, 2)).ToArray();
            LogInfo($"Step06_夹膜动作_夹爪_夹膜位->目标位->[{string.Join("|", targetList)}]补偿值->[{string.Join("|", offsetList)}]");
            var speed1 = Jaw1_Axis.GetVelocityCurve(position);
            var speed2 = Jaw2_Axis.GetVelocityCurve(position);
            var speed3 = Jaw3_Axis.GetVelocityCurve(position);
            var speed4 = Jaw4_Axis.GetVelocityCurve(position);
            var speed5 = Jaw5_Axis.GetVelocityCurve(position);
            var speed6 = Jaw6_Axis.GetVelocityCurve(position);
            var speed7 = Jaw7_Axis.GetVelocityCurve(position);
            await Parallel.ForEachAsync([(Jaw1_Axis, p1, speed1), (Jaw2_Axis, p2, speed2), (Jaw3_Axis, p3, speed3), (Jaw4_Axis, p4, speed4), (Jaw5_Axis, p5, speed5), (Jaw6_Axis, p6, speed6), (Jaw7_Axis, p7, speed7)], CancellationToken, async (x, t) => await x.Item1.MoveToAsync(x.Item2, x.Item3, t));
            await Task.Delay(100, CancellationToken);
            LogInfo($"Step06_夹膜动作_夹爪_夹膜位->[结束]");
            Step = SiMoStationRunStep.Step07_夹膜动作_气缸夹紧;
        }
        async Task Step07_夹膜动作_气缸夹紧()
        {
            if (Step != SiMoStationRunStep.Step07_夹膜动作_气缸夹紧) return;
            OnStepChanged("Step07_夹膜动作_气缸夹紧");
            LogInfo($"Step07_夹膜动作_气缸夹紧->[开始]");
            foreach (var item in Cylinders)
            {
                item.TakeBack();
            }
            await Task.Delay(motionTimeOption.JiaMoCylinderTakeBackDelay, CancellationToken);
            var sensor = SignalPanel.Signal.IsUseSiMo1 ? Electronic.DI79_夹爪闭合光纤1 : Electronic.DI81_夹爪闭合光纤2;
            if (_inspectorOption.IsJawOpenCloseGuangXianShield == false)//光纤不屏蔽
            {
                if (!await Judger.Sure(() => sensor.Value, CancellationToken, motionTimeOption.JiaOpenCloeSensorTimeout, 200))
                {
                    JawSensorError = true;
                    LogError($"Step07_夹膜动作_气缸夹紧->[夹爪光纤位置报警!");
                    await Task.Delay(500);
                    return;
                }
            }
            LogInfo($"Step07_夹膜动作_气缸夹紧->[结束]");
            Step = SiMoStationRunStep.Step08_撕膜动作_过渡位;
        }
        async Task Step08_撕膜动作_过渡位()
        {
            if (Step != SiMoStationRunStep.Step08_撕膜动作_过渡位) return;
            OnStepChanged("Step08_撕膜动作_过渡位");
            LogInfo($"Step08_撕膜动作_过渡位->[开始]");
            ushort[] axisId = [(ushort)DingSheng_Axis.NoId, (ushort)Jaw1_Axis.NoId, (ushort)Jaw2_Axis.NoId, (ushort)Jaw3_Axis.NoId, (ushort)Jaw4_Axis.NoId, (ushort)Jaw5_Axis.NoId, (ushort)Jaw6_Axis.NoId, (ushort)Jaw7_Axis.NoId];
            string guoduPosition = SignalPanel.Signal.IsUseSiMo1 ? Jaw_撕膜过渡位1 : Jaw_撕膜过渡位2;
            var p1 = Jaw1_Axis.GetTargetPosition(guoduPosition) + SignalPanel.Signal.JawOffsets[0];
            var p2 = Jaw2_Axis.GetTargetPosition(guoduPosition) + SignalPanel.Signal.JawOffsets[1];
            var p3 = Jaw3_Axis.GetTargetPosition(guoduPosition) + SignalPanel.Signal.JawOffsets[2];
            var p4 = Jaw4_Axis.GetTargetPosition(guoduPosition) + SignalPanel.Signal.JawOffsets[3];
            var p5 = Jaw5_Axis.GetTargetPosition(guoduPosition) + SignalPanel.Signal.JawOffsets[4];
            var p6 = Jaw6_Axis.GetTargetPosition(guoduPosition) + SignalPanel.Signal.JawOffsets[5];
            var p7 = Jaw7_Axis.GetTargetPosition(guoduPosition) + SignalPanel.Signal.JawOffsets[6];
            //double[] guodupositions = [DingSheng_Axis.GetTargetPosition(Ds_撕膜过渡位), .. JawAxises.Select(x => x.GetTargetPosition(guoduPosition))];
            var targetList = new List<double>() { p1, p2, p3, p3, p4, p5, p6, p7 };
            var offsetList = SignalPanel.Signal.JawOffsets;
            targetList = targetList.Select(x => Math.Round(x, 2)).ToList();
            offsetList = offsetList.Select(x => Math.Round(x, 2)).ToArray();
            double[] guodupositions = [DingSheng_Axis.GetTargetPosition(Ds_撕膜过渡位), p1, p2, p3, p3, p4, p5, p6, p7];
            LogInfo($"Step08_撕膜动作_过渡位->[{string.Join("|", targetList)}]补偿值->[{string.Join("|", offsetList)}]");
            Electronic.Controller.AbsoluteMove(0, axisId, guodupositions, SiMoVelocityCurve);
            await Judger.Sure(() => Electronic.Controller.IsDone(0), CancellationToken);
            await CheckCancellationToken();
            LogInfo($"Step08_撕膜动作_过渡位->[结束]");
            Step = SiMoStationRunStep.Step09_撕膜动作_夹爪_结束位;
        }
        async Task Step09_撕膜动作_夹爪_结束位()
        {
            if (Step != SiMoStationRunStep.Step09_撕膜动作_夹爪_结束位) return;
            OnStepChanged("Step09_撕膜动作_夹爪_结束位");
            LogInfo($"Step09_撕膜动作_夹爪_结束位->[开始]");
            ushort[] axisId = [(ushort)Jaw1_Axis.NoId, (ushort)Jaw2_Axis.NoId, (ushort)Jaw3_Axis.NoId, (ushort)Jaw4_Axis.NoId, (ushort)Jaw5_Axis.NoId, (ushort)Jaw6_Axis.NoId, (ushort)Jaw7_Axis.NoId];
            string endPosition = SignalPanel.Signal.IsUseSiMo1 ? Jaw_撕膜结束位1 : Jaw_撕膜结束位2;
            //double[] endPositions = [.. JawAxises.Select(x => x.GetTargetPosition(endPosition))];
            var p1 = Jaw1_Axis.GetTargetPosition(endPosition) + SignalPanel.Signal.JawOffsets[0];
            var p2 = Jaw2_Axis.GetTargetPosition(endPosition) + SignalPanel.Signal.JawOffsets[1];
            var p3 = Jaw3_Axis.GetTargetPosition(endPosition) + SignalPanel.Signal.JawOffsets[2];
            var p4 = Jaw4_Axis.GetTargetPosition(endPosition) + SignalPanel.Signal.JawOffsets[3];
            var p5 = Jaw5_Axis.GetTargetPosition(endPosition) + SignalPanel.Signal.JawOffsets[4];
            var p6 = Jaw6_Axis.GetTargetPosition(endPosition) + SignalPanel.Signal.JawOffsets[5];
            var p7 = Jaw7_Axis.GetTargetPosition(endPosition) + SignalPanel.Signal.JawOffsets[6];
            double[] endPositions = new double[] { p1, p2, p3, p4, p5, p6, p7 };
            LogInfo($"Step08_撕膜动作_过渡位->[轴移动]");
            Electronic.Controller.AbsoluteMove(0, axisId, endPositions, SiMoVelocityCurve);
            await Judger.Sure(() => Electronic.Controller.IsDone(0), CancellationToken);
            await CheckCancellationToken();
            LogInfo($"Step09_撕膜动作_夹爪_结束位->[结束]");
            Step = SiMoStationRunStep.Step10_撕膜动作_顶升_结束位;
        }
        async Task Step10_撕膜动作_顶升_结束位()
        {
            if (Step != SiMoStationRunStep.Step10_撕膜动作_顶升_结束位) return;
            OnStepChanged("Step10_撕膜动作_顶升_结束位");
            LogInfo($"Step10_撕膜动作_顶升_结束位->[开始]");
            await DingSheng_Axis.MoveToAsync(DingSheng_Axis.GetTargetPosition(Ds_撕膜结束位), SiMoVelocityCurve, CancellationToken);
            await Task.Delay(100, CancellationToken);
            Status.HasProducts = [true, true, true, true, true, true, true];
            SignalPanel.Signal.SiMoCompleted = true;
            LogInfo($"Step10_撕膜动作_顶升_结束位->[结束]");
            Step = SiMoStationRunStep.Step11_抛膜动作_顶升_抛膜上;
        }
        async Task Step11_抛膜动作_顶升_抛膜上()
        {
            if (Step != SiMoStationRunStep.Step11_抛膜动作_顶升_抛膜上) return;
            OnStepChanged("Step11_抛膜动作_顶升_抛膜上");
            LogInfo($"Step11_抛膜动作_顶升_抛膜上->[开始]");
            string ps = SignalPanel.Signal.IsUseSiMo1 ? Ds_抛膜上1 : Ds_抛膜上2;
            await DingSheng_Axis.MoveToAsync(ps, CancellationToken);
            var cylinder = SignalPanel.Signal.IsUseSiMo1 ? YaMo1_Cylinder : YaMo2_Cylinder;
            cylinder.TakeBack();//气缸张开
            await Task.Delay(motionTimeOption.YaMoCylinderTakeBackDelay, CancellationToken);
            LogInfo($"Step11_抛膜动作_顶升_抛膜上->[结束]");
            Step = SiMoStationRunStep.Step12_抛膜动作_夹爪_抛膜位;
        }
        async Task Step12_抛膜动作_夹爪_抛膜位()
        {
            if (Step != SiMoStationRunStep.Step12_抛膜动作_夹爪_抛膜位) return;
            OnStepChanged("Step12_抛膜动作_夹爪_抛膜位");
            LogInfo($"Step12_抛膜动作_夹爪_抛膜位->[开始]");
            var judgerfeeder = SignalPanel.Signal.IsUseSiMo1 ? Feeder1 : Feeder2;
            await Judger.Sure(() => judgerfeeder.Axis.IsDone, CancellationToken);
            await judgerfeeder.NianMo2(_inspectorOption.FeedarOneStepDistance, _inspectorOption.FeedarLongStepDistance, _inspectorOption.FeedarSteps, CancellationToken, true);
            await Judger.Sure(() => judgerfeeder.Axis.IsDone, CancellationToken);
            string jps = SignalPanel.Signal.IsUseSiMo1 ? Jaw_抛膜位1 : Jaw_抛膜位2;
            LogInfo($"Step12_抛膜动作_夹爪_抛膜位->[飞达已就绪,夹爪步进到抛膜位]");
            await JawAxises.MoveToAsync(jps, CancellationToken);
            await CheckCancellationToken();
            LogInfo($"Step12_抛膜动作_夹爪_抛膜位->[结束]");
            Step = SiMoStationRunStep.Step13_抛膜动作_顶升_抛膜下;
        }
        async Task Step13_抛膜动作_顶升_抛膜下()
        {
            if (Step != SiMoStationRunStep.Step13_抛膜动作_顶升_抛膜下) return;
            OnStepChanged("Step13_抛膜动作_顶升_抛膜下");
            LogInfo($"Step13_抛膜动作_顶升_抛膜下->[开始]");
            var cylinder = SignalPanel.Signal.IsUseSiMo1 ? YaMo1_Cylinder : YaMo2_Cylinder;
            string ps = SignalPanel.Signal.IsUseSiMo1 ? Ds_抛膜下1 : Ds_抛膜下2;
            await DingSheng_Axis.MoveToAsync(ps, CancellationToken);
            await CheckCancellationToken();
            LogInfo($"Step13_抛膜动作_顶升_抛膜下->[顶升步进已到抛膜下]");
            cylinder.PushOut();//闭合
            await Task.Delay(motionTimeOption.YaMoCylinderPushOutDelay, CancellationToken);
            LogInfo($"Step13_抛膜动作_顶升_抛膜下->[压膜气缸已闭合]");
            foreach (var item in Cylinders)
            {
                item.PushOut();
            }
            await Task.Delay(motionTimeOption.JiaMoCylinderPushOutDelay);
            LogInfo($"Step13_抛膜动作_顶升_抛膜下->[夹爪张开]");
            var sensor = SignalPanel.Signal.IsUseSiMo1 ? Electronic.DI80_夹爪张开光纤1 : Electronic.DI82_夹爪张开光纤2;
            if (_inspectorOption.IsJawOpenCloseGuangXianShield == false)//不屏蔽光纤
            {
                if (!await Judger.Sure(() => sensor.Value, CancellationToken, motionTimeOption.JiaOpenCloeSensorTimeout, 200))
                {
                    JawSensorError = true;
                    LogError($"Step13_抛膜动作_顶升_抛膜下->[夹爪光纤位置报警!");
                    await Task.Delay(500);
                    return;
                }
            }
            LogInfo($"Step13_抛膜动作_顶升_抛膜下->[结束]");
            Step = SiMoStationRunStep.Step14_抛膜动作_夹爪_等待位;
        }
        async Task Step14_抛膜动作_夹爪_等待位()
        {
            if (Step != SiMoStationRunStep.Step14_抛膜动作_夹爪_等待位) return;
            OnStepChanged("Step14_抛膜动作_夹爪_等待位");
            LogInfo($"Step14_抛膜动作_夹爪_等待位->[开始,飞达开始粘膜]");
            var feeder = SignalPanel.Signal.IsUseSiMo1 ? Feeder1 : Feeder2;
            _ = feeder.NianMo2(_inspectorOption.FeedarOneStepDistance, _inspectorOption.FeedarLongStepDistance, _inspectorOption.FeedarSteps, CancellationToken, false);
            if (SignalPanel.Signal.IsUseSiMo1)
                Status.Feeder1Step++;
            else
                Status.Feeder2Step++;
            string ps = SignalPanel.Signal.IsUseSiMo1 ? Jaw_夹膜等待位1 : Jaw_夹膜等待位2;
            await JawAxises.MoveToAsync(ps, CancellationToken);
            await CheckCancellationToken();
            LogInfo($"Step14_抛膜动作_夹爪_等待位->[夹爪步进已到等待位,完成抛膜动作]");
            if (_inspectorOption.IsJawGuangXianShield == false)
            {
                var sensors = SignalPanel.Signal.IsUseSiMo1 ? JawSensors1 : JawSensors2;
                var selectedSensor = Functions.SelectObjects(sensors.ToList(), BanYunStation.Status.NozzleStatus.Select(x => x != TrayPointStatus.Empty || x != TrayPointStatus.NG).ToList());
                var state = await Judger.Sure(() => selectedSensor.All(x => x.Value == false), CancellationToken, motionTimeOption.JiaDoneSensorTimeout);
                if (!state)
                {
                    JawSensorError = true;
                    LogError($"Step14_抛膜动作_夹爪_等待位->[夹爪光纤位置报警!");
                    await Task.Delay(500);
                    return;
                }
            }
            Status.HasProducts = [false, false, false, false, false, false, false];
            LogInfo($"Step14_抛膜动作_夹爪_等待位->[结束]");
            Step = SiMoStationRunStep.Step01_获取撕膜位;
        }

        #region TODO 步骤拆解之前动作
        //async Task Step04_夹膜动作()
        //{
        //    if (Step != SiMoStationRunStep.Step04_夹膜动作) return;
        //    OnStepChanged("Step04_夹膜动作");
        //    LogInfo($"Step04_夹膜动作->[开始,移动夹膜位]");
        //    await DingSheng_Axis.MoveToAsync(Ds_夹膜位, CancellationToken);
        //    foreach (var item in Cylinders)
        //    {
        //        item.PushOut();
        //    }
        //    await Task.Delay(200);
        //    LogInfo($"Step04_夹膜动作->[夹爪已打开,夹爪伺服移动到夹膜位]");
        //    string position = SignalPanel.Signal.IsUseSiMo1 ? Jaw_夹膜位1 : Jaw_夹膜位2;
        //    double tolerance = 5;
        //    if (SignalPanel.Signal.JawOffsets.Any(x => Math.Abs(x) > tolerance))
        //    {
        //        XOffsetLimitError = true;
        //        LogError($"Step04_夹膜动作->[夹爪X轴纠偏量超上限5mm:{tolerance}]!");
        //        await Task.Delay(1000);
        //        return;
        //    }
        //    var p1 = Jaw1_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[0];
        //    var p2 = Jaw2_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[1];
        //    var p3 = Jaw3_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[2];
        //    var p4 = Jaw4_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[3];
        //    var p5 = Jaw5_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[4];
        //    var p6 = Jaw6_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[5];
        //    var p7 = Jaw7_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[6];
        //    var speed1 = Jaw1_Axis.GetVelocityCurve(position);
        //    var speed2 = Jaw2_Axis.GetVelocityCurve(position);
        //    var speed3 = Jaw3_Axis.GetVelocityCurve(position);
        //    var speed4 = Jaw4_Axis.GetVelocityCurve(position);
        //    var speed5 = Jaw5_Axis.GetVelocityCurve(position);
        //    var speed6 = Jaw6_Axis.GetVelocityCurve(position);
        //    var speed7 = Jaw7_Axis.GetVelocityCurve(position);

        //    await Parallel.ForEachAsync([(Jaw1_Axis, p1, speed1), (Jaw2_Axis, p2, speed2), (Jaw3_Axis, p3, speed3), (Jaw4_Axis, p4, speed4), (Jaw5_Axis, p5, speed5), (Jaw6_Axis, p6, speed6), (Jaw7_Axis, p7, speed7)], CancellationToken, async (x, t) => await x.Item1.MoveToAsync(x.Item2, x.Item3, t));
        //    await Task.Delay(100);
        //    LogInfo($"Step04_夹膜动作->[夹爪伺服已到夹膜位,夹爪闭合]");
        //    foreach (var item in Cylinders)
        //    {
        //        item.TakeBack();
        //    }
        //    await Task.Delay(500);
        //    var sensor2 = SignalPanel.Signal.IsUseSiMo1 ? Electronic.DI79_夹爪闭合光纤1 : Electronic.DI81_夹爪闭合光纤2;
        //    if (!_inspectorOption.IsJawOpenCloseGuangXianShield)
        //    {
        //        if (!await Judger.Sure(() => sensor2.Value, CancellationToken, 3000))
        //        {
        //            JawSensorError = true;
        //            await Task.Delay(500);
        //            return;
        //        }
        //    }
        //    LogInfo($"Step04_夹膜动作->[结束,夹爪已闭合]");
        //    Step = SiMoStationRunStep.Step06_撕膜动作;
        //}
        //async Task Step06_撕膜动作()
        //{
        //    if (Step != SiMoStationRunStep.Step06_撕膜动作) return;
        //    OnStepChanged("Step06_撕膜动作");
        //    LogInfo($"Step06_撕膜动作->[开始撕膜(直线插补)]");
        //    ushort[] axisId = [(ushort)DingSheng_Axis.NoId, (ushort)Jaw1_Axis.NoId, (ushort)Jaw2_Axis.NoId, (ushort)Jaw3_Axis.NoId, (ushort)Jaw4_Axis.NoId, (ushort)Jaw5_Axis.NoId, (ushort)Jaw6_Axis.NoId, (ushort)Jaw7_Axis.NoId];

        //    ushort[] axisId2 = [(ushort)Jaw1_Axis.NoId, (ushort)Jaw2_Axis.NoId, (ushort)Jaw3_Axis.NoId, (ushort)Jaw4_Axis.NoId, (ushort)Jaw5_Axis.NoId, (ushort)Jaw6_Axis.NoId, (ushort)Jaw7_Axis.NoId];

        //    string endPosition = SignalPanel.Signal.IsUseSiMo1 ? Jaw_撕膜结束位1 : Jaw_撕膜结束位2;
        //    string guoduPosition = SignalPanel.Signal.IsUseSiMo1 ? Jaw_撕膜过渡位1 : Jaw_撕膜过渡位2;
        //    double[] guodupositions = [DingSheng_Axis.GetTargetPosition(Ds_撕膜过渡位), .. JawAxises.Select(x => x.GetTargetPosition(guoduPosition))];
        //    double[] endPositions = [.. JawAxises.Select(x => x.GetTargetPosition(endPosition))];
        //    //var siMoSpeed = DingSheng_Axis.GetVelocityCurve(Ds_撕膜结束位);
        //    VelocityCurve siMoVelocityCurve = new VelocityCurve() { Maxvel = _inspectorOption.SiMoSpeed, Tdec = 0.1, Tacc = 0.1 };
        //    LogInfo($"Step06_撕膜动作->[撕膜动作过渡位开始]");
        //    Electronic.Controller.AbsoluteMove(0, axisId, guodupositions, siMoVelocityCurve);
        //    await Judger.Sure(() => Electronic.Controller.IsDone(0), CancellationToken);
        //    LogInfo($"Step06_撕膜动作->[撕膜动作过渡位已完成,X轴移动到撕膜结束位开始]");
        //    Electronic.Controller.AbsoluteMove(0, axisId2, endPositions, siMoVelocityCurve);
        //    await Judger.Sure(() => Electronic.Controller.IsDone(0), CancellationToken);
        //    LogInfo($"Step06_撕膜动作->[撕膜动作X轴移动到撕膜结束位完成,Z轴移动结束位开始]");
        //    await DingSheng_Axis.MoveToAsync(DingSheng_Axis.GetTargetPosition(Ds_撕膜结束位), siMoVelocityCurve, CancellationToken);
        //    LogInfo($"Step06_撕膜动作->[撕膜动作Z轴移动结束位完成]");
        //    await Task.Delay(100);
        //    LogInfo($"Step06_撕膜动作->[开结束)]");
        //    Status.HasProducts = [true, true, true, true, true, true, true];
        //    SignalPanel.Signal.SiMoCompleted = true;
        //    Step = SiMoStationRunStep.Step07_抛膜动作;
        //}
        //async Task Step07_抛膜动作()
        //{
        //    if (Step != SiMoStationRunStep.Step07_抛膜动作) return;
        //    OnStepChanged("Step07_抛膜动作");
        //    LogInfo($"Step07_抛膜动作->[顶升步进到抛膜上位]");
        //    string ps = SignalPanel.Signal.IsUseSiMo1 ? Ds_抛膜上1 : Ds_抛膜上2;
        //    await DingSheng_Axis.MoveToAsync(ps, CancellationToken);
        //    var cylinder = SignalPanel.Signal.IsUseSiMo1 ? YaMo1_Cylinder : YaMo2_Cylinder;
        //    LogInfo($"Step07_抛膜动作->[顶升步进已到抛膜上,压膜气缸打开]");
        //    cylinder.TakeBack();//张开
        //    await Task.Delay(100);
        //    var judgerfeeder = SignalPanel.Signal.IsUseSiMo1 ? Feeder1 : Feeder2;
        //    LogInfo($"Step07_抛膜动作->[判断飞达是否运动指令执行完成]");
        //    await Judger.Sure(() => judgerfeeder.Axis.IsDone, CancellationToken);
        //    await judgerfeeder.NianMo2(_inspectorOption.FeedarOneStepDistance, _inspectorOption.FeedarLongStepDistance, _inspectorOption.FeedarSteps, CancellationToken, true);
        //    await Judger.Sure(() => judgerfeeder.Axis.IsDone, CancellationToken);
        //    LogInfo($"Step07_抛膜动作->[飞达运动执行已经完成]");
        //    string jps = SignalPanel.Signal.IsUseSiMo1 ? Jaw_抛膜位1 : Jaw_抛膜位2;
        //    LogInfo($"Step07_抛膜动作->[压膜气缸已打开,开始夹爪步进到抛膜位]");
        //    await JawAxises.MoveToAsync(jps, CancellationToken);
        //    LogInfo($"Step07_抛膜动作->[夹爪步进已到抛膜位,顶升步进到抛膜下]");
        //    string ps2 = SignalPanel.Signal.IsUseSiMo1 ? Ds_抛膜下1 : Ds_抛膜下2;
        //    await DingSheng_Axis.MoveToAsync(ps2, CancellationToken);
        //    LogInfo($"Step07_抛膜动作->[顶升步进已到抛膜下,压膜气缸闭合]");
        //    cylinder.PushOut();//闭合
        //    await Task.Delay(100);
        //    LogInfo($"Step07_抛膜动作->[压膜气缸已闭合，夹爪打开]");
        //    foreach (var item in Cylinders)
        //    {
        //        item.PushOut();
        //    }
        //    await Task.Delay(200);
        //    var sensor1 = SignalPanel.Signal.IsUseSiMo1 ? Electronic.DI80_夹爪张开光纤1 : Electronic.DI82_夹爪张开光纤2;
        //    if (!_inspectorOption.IsJawOpenCloseGuangXianShield)
        //    {
        //        if (!await Judger.Sure(() => sensor1.Value, CancellationToken, 3000, 200))
        //        {
        //            JawSensorError = true;
        //            await Task.Delay(500);
        //            return;
        //        }
        //    }
        //    LogInfo($"Step07_抛膜动作->[夹爪已打开,飞达开始粘膜]");
        //    var feeder = SignalPanel.Signal.IsUseSiMo1 ? Feeder1 : Feeder2;
        //    _ = feeder.NianMo2(_inspectorOption.FeedarOneStepDistance, _inspectorOption.FeedarLongStepDistance, _inspectorOption.FeedarSteps, CancellationToken, false);
        //    if (SignalPanel.Signal.IsUseSiMo1)
        //        Status.Feeder1Step++;
        //    else
        //        Status.Feeder2Step++;
        //    LogInfo($"Step07_抛膜动作->[夹爪已打开,夹爪步进开始到夹膜等待位]");
        //    string ps3 = SignalPanel.Signal.IsUseSiMo1 ? Jaw_夹膜等待位1 : Jaw_夹膜等待位2;
        //    await JawAxises.MoveToAsync(ps3, CancellationToken);
        //    LogInfo($"Step07_抛膜动作->[夹爪步进已到等待位,完成抛膜动作]");
        //    if (!_inspectorOption.IsJawGuangXianShield)
        //    {
        //        var sensors = SignalPanel.Signal.IsUseSiMo1 ? JawSensors1 : JawSensors2;
        //        var selectedSensor = Functions.SelectObjects(sensors.ToList(), BanYunStation.Status.NozzleStatus.Select(x => x != TrayPointStatus.Empty || x != TrayPointStatus.NG).ToList());
        //        if (await Judger.Sure(() => selectedSensor.Any(x => x.Value), CancellationToken))
        //        {
        //            JawSensorError = true;
        //            await Task.Delay(500);
        //            return;
        //        }
        //    }
        //    Status.HasProducts = [false, false, false, false, false, false, false];
        //    LogInfo($"Step07_抛膜动作->[结束]");
        //    Step = SiMoStationRunStep.Step01_获取撕膜位;
        //}
        #endregion
        #endregion

        #region 状态恢复流程
        SiMoRunniningStatus _preRunStatus;
        /// <summary>
        /// 状态恢复流程异常
        /// </summary>
        bool _isRecoverPreRunningError = false;
        /// <summary>
        /// 复到到停止运行之前检测状态
        /// </summary>
        /// <returns></returns>
        protected async Task RecoverPreRunning()
        {
            try
            {
                LogInfo($"运行状态恢复->[开始]");
                _isRecoverPreRunningError = false;
                _preRunStatus = Status.Clone();
                if (Step == SiMoStationRunStep.Step02_顶升夹膜位 || Step == SiMoStationRunStep.Step04_夹膜动作_Z轴顶升)
                {
                    for (int i = 0; i < JawAxises.Count(); i++)
                    {
                        if (!JawAxises[i].CheckIsInPosition(Status.JaxAxisesPositions[i]))
                        {
                            await JawAxises[i].MoveToAsync(Status.JaxAxisesPositions[i]);
                        }
                    }
                }
                else if (Step == SiMoStationRunStep.Step03_等待搬运完成 || Step == SiMoStationRunStep.Step05_夹膜动作_气缸张开)
                {
                    for (int i = 0; i < JawAxises.Count(); i++)//恢复夹爪步骤X轴
                    {
                        if (!JawAxises[i].CheckIsInPosition(Status.JaxAxisesPositions[i]))
                        {
                            await JawAxises[i].MoveToAsync(Status.JaxAxisesPositions[i]);
                        }
                    }
                    if (!DingSheng_Axis.CheckIsInPosition(Status.DSAxisPositions))//恢复夹爪步顶升Z轴
                    {
                        await DingSheng_Axis.MoveToAsync(Status.DSAxisPositions);
                    }
                }
                else if (Step == SiMoStationRunStep.Step06_夹膜动作_夹爪_夹膜位)
                {
                    if (!DingSheng_Axis.CheckIsInPosition(Status.DSAxisPositions))//恢复夹爪步顶升Z轴
                    {
                        string jaw_夹膜等待位 = SignalPanel.Signal.IsUseSiMo1 ? Jaw_夹膜等待位1 : Jaw_夹膜等待位2;
                        for (int i = 0; i < JawAxises.Count(); i++)
                        {
                            if (!JawAxises[i].CheckIsInPosition(jaw_夹膜等待位))
                            {
                                await JawAxises[i].MoveToAsync(jaw_夹膜等待位, CancellationToken);
                            }
                        }
                        await DingSheng_Axis.MoveToAsync(Status.DSAxisPositions);
                    }
                    for (int i = 0; i < Cylinders.Count; i++)//恢复气缸状态张开
                    {
                        var jawCylinderState = Status.JawCylinderStates[i];
                        if (!Cylinders[i].VerifyState(jawCylinderState))
                        {
                            await Cylinders[i].RecoveryState(jawCylinderState, CancellationToken);
                        }
                    }
                    for (int i = 0; i < JawAxises.Count(); i++)//恢复夹爪步骤X轴
                    {
                        if (!JawAxises[i].CheckIsInPosition(Status.JaxAxisesPositions[i]))
                        {
                            await JawAxises[i].MoveToAsync(Status.JaxAxisesPositions[i]);
                        }
                    }
                }
                else if (Step == SiMoStationRunStep.Step07_夹膜动作_气缸夹紧)
                {
                    if (!DingSheng_Axis.CheckIsInPosition(Status.DSAxisPositions))//恢复夹爪步顶升Z轴
                    {
                        for (int i = 0; i < Cylinders.Count; i++)//恢复气缸状态全不张开
                        {
                            await Cylinders[i].PushOutAsync();
                        }
                        await Task.Delay(500, CancellationToken);
                        string jaw_夹膜等待位 = SignalPanel.Signal.IsUseSiMo1 ? Jaw_夹膜等待位1 : Jaw_夹膜等待位2;
                        for (int i = 0; i < JawAxises.Count(); i++)
                        {
                            if (!JawAxises[i].CheckIsInPosition(jaw_夹膜等待位))
                            {
                                await JawAxises[i].MoveToAsync(jaw_夹膜等待位, CancellationToken);
                            }
                        }
                        await DingSheng_Axis.MoveToAsync(Status.DSAxisPositions);
                    }
                    for (int i = 0; i < JawAxises.Count(); i++)
                    {
                        if (!JawAxises[i].CheckIsInPosition(Status.JaxAxisesPositions[i]))//恢复夹爪步骤X轴
                        {
                            if (Cylinders[i].IsBack())//如果气缸闭合就推开，再去移动X轴
                                await Cylinders[i].PushOutAsync();
                            await JawAxises[i].MoveToAsync(Status.JaxAxisesPositions[i]);
                        }
                    }
                    for (int i = 0; i < Cylinders.Count; i++)//恢复气缸状态张开
                    {
                        var jawCylinderState = Status.JawCylinderStates[i];
                        if (!Cylinders[i].VerifyState(jawCylinderState))
                        {
                            await Cylinders[i].RecoveryState(jawCylinderState, CancellationToken);
                        }
                    }
                }
                else if (Step == SiMoStationRunStep.Step08_撕膜动作_过渡位 || Step == SiMoStationRunStep.Step09_撕膜动作_夹爪_结束位 || Step == SiMoStationRunStep.Step10_撕膜动作_顶升_结束位)
                {
                    for (int i = 0; i < Cylinders.Count; i++)
                    {
                        var jawCylinderState = Status.JawCylinderStates[i];
                        if (!Cylinders[i].VerifyState(jawCylinderState))
                        {
                            await Cylinders[i].RecoveryState(jawCylinderState, CancellationToken);
                        }
                    }
                }
                else if (Step == SiMoStationRunStep.Step11_抛膜动作_顶升_抛膜上)
                {
                    //暂无
                }
                else if (Step == SiMoStationRunStep.Step12_抛膜动作_夹爪_抛膜位)
                {
                    if (!DingSheng_Axis.CheckIsInPosition(Status.DSAxisPositions))//恢复夹爪步顶升Z轴
                    {
                        string jaw_夹膜等待位 = SignalPanel.Signal.IsUseSiMo1 ? Jaw_夹膜等待位1 : Jaw_夹膜等待位2;
                        for (int i = 0; i < JawAxises.Count(); i++)
                        {
                            if (!JawAxises[i].CheckIsInPosition(jaw_夹膜等待位))
                            {
                                await JawAxises[i].MoveToAsync(jaw_夹膜等待位, CancellationToken);
                            }
                        }
                        await DingSheng_Axis.MoveToAsync(Status.DSAxisPositions);
                    }
                }
                else if (Step == SiMoStationRunStep.Step13_抛膜动作_顶升_抛膜下)//不好判断，因为如果执行过了膜已经粘贴在胶带上面了
                {
                    if (DingSheng_Axis.CheckIsInPosition(Ds_抛膜下1) || DingSheng_Axis.CheckIsInPosition(Ds_抛膜下2))
                    {

                    }
                }
                else if (Step == SiMoStationRunStep.Step14_抛膜动作_夹爪_等待位)
                {
                    //暂无
                }
                LogInfo($"运行状态恢复->[结束]");
            }
            catch (Exception ex)
            {
                _isRecoverPreRunningError = true;
                Root.Stop();
                LogError($"运行状态恢复->[异常]{ex.Message}", ex);
            }
        }
        void ThrowException(string message)
        {
            throw new InvalidOperationException(message);
        }
        #endregion

        #region 公共方法
        public void ClearAlarm()
        {
            JawSensorError = false;
            JawPositionError = false;
            XOffsetLimitError = false;
        }
        public void OnStepChanged(string step)
        {
            StepsChanged?.SafeInvoke(this, step);
        }
        IOptionRepository _optionRepository;
        public override async Task InitializeAsync()
        {
            _optionRepository = Service.GetRequiredService<IOptionRepository>();
            _inspectorOption = _optionRepository.Get<InspectorOption>();
            Status = RunningStatus.GetRecord<SiMoRunniningStatus>("SiMoStation.json");
            Feeder1.Count = Status.Feeder1Step;
            Feeder2.Count = Status.Feeder2Step;
            Logger = Service.GetService<ILoggerFactory>().CreateLogger("SiMoStation");
            await base.InitializeAsync();
        }
        protected IEnumerable<DmcAxis> GetAxes()
        {
            return Automatics.Where(x => x is DmcAxis).Cast<DmcAxis>().ToArray();
        }
        #endregion

        #region 私有方法
        private void Feeder1_StepCountChanged(object? sender, int e)
        {
            Status.Feeder1Step = e;
        }
        private void Feeder2_StepCountChanged(object? sender, int e)
        {
            Status.Feeder2Step = e;
        }
        /// <summary>
        /// 检查令牌是否被取消
        /// </summary>
        /// <returns></returns>
        private async Task CheckCancellationToken()
        {
            await Task.Delay(1, CancellationToken);
        }
        private void SaveRuningRecordState()
        {
            if (_isInitialized)
            {
                for (int i = 0; i < Cylinders.Count(); i++)
                {
                    if (Cylinders[i].IsPushOut())
                        Status.JawCylinderStates[i] = CylinderStates.PushOut;
                    if (Cylinders[i].IsBack())
                        Status.JawCylinderStates[i] = CylinderStates.TakeBack;
                }
                Status.DSAxisPositions = DingSheng_Axis.Current;
                Status.JaxAxisesPositions = JawAxises.Select(x => x.Current).ToArray();
            }
            #region 如果发生异常把之前状态赋值回去
            if (_isRecoverPreRunningError && _preRunStatus != null)
            {
                Status = _preRunStatus;
            }
            #endregion
            Status.Save();
        }
        //private void SaveRuningRecordStateInit()
        //{
        //    Status.DSAxisPositions = DingSheng_Axis.Current;
        //    Status.JaxAxisesPositions = JawAxises.Select(x => x.Current).ToArray();
        //    Status.Save();
        //}
        #endregion

        #region 防呆方法

        #endregion
    }

}

public enum SiMoStationRunStep
{
    Step01_获取撕膜位,
    Step02_顶升夹膜位,
    Step03_等待搬运完成,
    Step04_夹膜动作_Z轴顶升,
    Step05_夹膜动作_气缸张开,
    Step06_夹膜动作_夹爪_夹膜位,
    Step07_夹膜动作_气缸夹紧,
    Step08_撕膜动作_过渡位,
    Step09_撕膜动作_夹爪_结束位,
    Step10_撕膜动作_顶升_结束位,
    Step11_抛膜动作_顶升_抛膜上,
    Step12_抛膜动作_夹爪_抛膜位,
    Step13_抛膜动作_顶升_抛膜下,
    Step14_抛膜动作_夹爪_等待位,
}

#region TODO 旧
//public class SiMoStation : StationBase<SiMoStationOption>, ISuportClearAlarm
//{
//    #region 字段
//    public volatile BanYunStation BanYunStation;
//    public volatile Feeder FeiDaStation1;
//    public volatile Feeder FeiDaStation2;
//    public volatile SiMoRunniningStatus Status;

//    private const string Jaw_安全位 = "安全位";
//    private const string Jaw_夹膜等待位1 = "夹膜等待位1";
//    private const string Jaw_夹膜等待位2 = "夹膜等待位2";
//    private const string Jaw_夹膜位1 = "夹膜位1";
//    private const string Jaw_夹膜位2 = "夹膜位2";
//    private const string Jaw_撕膜结束位1 = "撕膜结束位1";
//    private const string Jaw_撕膜结束位2 = "撕膜结束位2";
//    private const string Jaw_撕膜过渡位1 = "撕膜过渡位1";
//    private const string Jaw_撕膜过渡位2 = "撕膜过渡位2";
//    private const string Jaw_抛膜位1 = "抛膜位1";
//    private const string Jaw_抛膜位2 = "抛膜位2";

//    private const string Ds_安全位 = "安全位";
//    private const string Ds_夹膜位 = "夹膜位";
//    private const string Ds_撕膜结束位 = "撕膜结束位";
//    private const string Ds_撕膜过渡位 = "撕膜过渡位";
//    private const string Ds_抛膜上1 = "抛膜上1";
//    private const string Ds_抛膜下1 = "抛膜下1";
//    private const string Ds_抛膜上2 = "抛膜上2";
//    private const string Ds_抛膜下2 = "抛膜下2";
//    private bool jawSensorError;
//    private bool isAxisSaveAlarm;
//    private bool vacuumAlarm;
//    private bool siMoActionTimeout;
//    private bool feedTrayError;
//    private bool jawPositionError;
//    private bool xOffsetLimitError;
//    private bool ngTrayError;
//    private InspectorOption _inspectorOption;
//    private bool _isInit;

//    #endregion

//    #region 硬件
//    [MotionPath(Ds_安全位)]
//    [MotionPath(Ds_夹膜位)]
//    [MotionPath(Ds_撕膜结束位)]
//    [MotionPath(Ds_撕膜过渡位)]
//    [MotionPath(Ds_抛膜上1)]
//    [MotionPath(Ds_抛膜下1)]
//    [MotionPath(Ds_抛膜上2)]
//    [MotionPath(Ds_抛膜下2)]
//    public IServoAxis DingSheng_Axis { get; private set; }

//    [MotionPath(Jaw_安全位)]
//    [MotionPath(Jaw_夹膜等待位1)]
//    [MotionPath(Jaw_夹膜等待位2)]
//    [MotionPath(Jaw_夹膜位1)]
//    [MotionPath(Jaw_夹膜位2)]
//    [MotionPath(Jaw_撕膜结束位1)]
//    [MotionPath(Jaw_撕膜结束位2)]
//    [MotionPath(Jaw_撕膜过渡位1)]
//    [MotionPath(Jaw_撕膜过渡位2)]
//    [MotionPath(Jaw_抛膜位1)]
//    [MotionPath(Jaw_抛膜位2)]
//    public IServoAxis Jaw1_Axis { get; private set; }
//    [MotionPath(Jaw_安全位)]
//    [MotionPath(Jaw_夹膜等待位1)]
//    [MotionPath(Jaw_夹膜等待位2)]
//    [MotionPath(Jaw_夹膜位1)]
//    [MotionPath(Jaw_夹膜位2)]
//    [MotionPath(Jaw_撕膜结束位1)]
//    [MotionPath(Jaw_撕膜结束位2)]
//    [MotionPath(Jaw_撕膜过渡位1)]
//    [MotionPath(Jaw_撕膜过渡位2)]
//    [MotionPath(Jaw_抛膜位1)]
//    [MotionPath(Jaw_抛膜位2)]
//    public IServoAxis Jaw2_Axis { get; private set; }
//    [MotionPath(Jaw_安全位)]
//    [MotionPath(Jaw_夹膜等待位1)]
//    [MotionPath(Jaw_夹膜等待位2)]
//    [MotionPath(Jaw_夹膜位1)]
//    [MotionPath(Jaw_夹膜位2)]
//    [MotionPath(Jaw_撕膜结束位1)]
//    [MotionPath(Jaw_撕膜结束位2)]
//    [MotionPath(Jaw_撕膜过渡位1)]
//    [MotionPath(Jaw_撕膜过渡位2)]
//    [MotionPath(Jaw_抛膜位1)]
//    [MotionPath(Jaw_抛膜位2)]
//    public IServoAxis Jaw3_Axis { get; private set; }
//    [MotionPath(Jaw_安全位)]
//    [MotionPath(Jaw_夹膜等待位1)]
//    [MotionPath(Jaw_夹膜等待位2)]
//    [MotionPath(Jaw_夹膜位1)]
//    [MotionPath(Jaw_夹膜位2)]
//    [MotionPath(Jaw_撕膜结束位1)]
//    [MotionPath(Jaw_撕膜结束位2)]
//    [MotionPath(Jaw_撕膜过渡位1)]
//    [MotionPath(Jaw_撕膜过渡位2)]
//    [MotionPath(Jaw_抛膜位1)]
//    [MotionPath(Jaw_抛膜位2)]
//    public IServoAxis Jaw4_Axis { get; private set; }
//    [MotionPath(Jaw_安全位)]
//    [MotionPath(Jaw_夹膜等待位1)]
//    [MotionPath(Jaw_夹膜等待位2)]
//    [MotionPath(Jaw_夹膜位1)]
//    [MotionPath(Jaw_夹膜位2)]
//    [MotionPath(Jaw_撕膜结束位1)]
//    [MotionPath(Jaw_撕膜结束位2)]
//    [MotionPath(Jaw_撕膜过渡位1)]
//    [MotionPath(Jaw_撕膜过渡位2)]
//    [MotionPath(Jaw_抛膜位1)]
//    [MotionPath(Jaw_抛膜位2)]
//    public IServoAxis Jaw5_Axis { get; private set; }
//    [MotionPath(Jaw_安全位)]
//    [MotionPath(Jaw_夹膜等待位1)]
//    [MotionPath(Jaw_夹膜等待位2)]
//    [MotionPath(Jaw_夹膜位1)]
//    [MotionPath(Jaw_夹膜位2)]
//    [MotionPath(Jaw_撕膜结束位1)]
//    [MotionPath(Jaw_撕膜结束位2)]
//    [MotionPath(Jaw_撕膜过渡位1)]
//    [MotionPath(Jaw_撕膜过渡位2)]
//    [MotionPath(Jaw_抛膜位1)]
//    [MotionPath(Jaw_抛膜位2)]
//    public IServoAxis Jaw6_Axis { get; private set; }
//    [MotionPath(Jaw_安全位)]
//    [MotionPath(Jaw_夹膜等待位1)]
//    [MotionPath(Jaw_夹膜等待位2)]
//    [MotionPath(Jaw_夹膜位1)]
//    [MotionPath(Jaw_夹膜位2)]
//    [MotionPath(Jaw_撕膜结束位1)]
//    [MotionPath(Jaw_撕膜结束位2)]
//    [MotionPath(Jaw_撕膜过渡位1)]
//    [MotionPath(Jaw_撕膜过渡位2)]
//    [MotionPath(Jaw_抛膜位1)]
//    [MotionPath(Jaw_抛膜位2)]
//    public IServoAxis Jaw7_Axis { get; private set; }

//    public CylinderEx Jaw1_Cylinder { get => Electronic.Cylinder_夹爪1气缸; }
//    public CylinderEx Jaw2_Cylinder { get => Electronic.Cylinder_夹爪2气缸; }
//    public CylinderEx Jaw3_Cylinder { get => Electronic.Cylinder_夹爪3气缸; }
//    public CylinderEx Jaw4_Cylinder { get => Electronic.Cylinder_夹爪4气缸; }
//    public CylinderEx Jaw5_Cylinder { get => Electronic.Cylinder_夹爪5气缸; }
//    public CylinderEx Jaw6_Cylinder { get => Electronic.Cylinder_夹爪6气缸; }
//    public CylinderEx Jaw7_Cylinder { get => Electronic.Cylinder_夹爪7气缸; }
//    public CylinderEx YaMo1_Cylinder { get => Electronic.Cylinder_飞达1压膜气缸; }
//    public CylinderEx YaMo2_Cylinder { get => Electronic.Cylinder_飞达2压膜气缸; }
//    public Feeder Feeder1 { get; }
//    public Feeder Feeder2 { get; }

//    public List<IServoAxis> JawAxises => [Jaw1_Axis, Jaw2_Axis, Jaw3_Axis, Jaw4_Axis, Jaw5_Axis, Jaw6_Axis, Jaw7_Axis];
//    public List<CylinderEx> Cylinders => [Jaw1_Cylinder, Jaw2_Cylinder, Jaw3_Cylinder, Jaw4_Cylinder, Jaw5_Cylinder, Jaw6_Cylinder, Jaw7_Cylinder];
//    public CardIoPoint[] JawSensors1 => [Electronic.DI65_夹爪膜检测光纤11, Electronic.DI66_夹爪膜检测光纤12, Electronic.DI67_夹爪膜检测光纤13, Electronic.DI68_夹爪膜检测光纤14, Electronic.DI69_夹爪膜检测光纤15, Electronic.DI70_夹爪膜检测光纤16, Electronic.DI71_夹爪膜检测光纤17];
//    public CardIoPoint[] JawSensors2 => [Electronic.DI72_夹爪膜检测光纤21, Electronic.DI73_夹爪膜检测光纤22, Electronic.DI74_夹爪膜检测光纤23, Electronic.DI75_夹爪膜检测光纤24, Electronic.DI76_夹爪膜检测光纤25, Electronic.DI77_夹爪膜检测光纤26, Electronic.DI78_夹爪膜检测光纤27];

//    #endregion

//    #region 报警

//    [Alarm(true, AlarmLevel.Error, "夹爪光纤位置报警", Logical.Equal)]
//    public bool JawSensorError { get => jawSensorError; set => NotifyAlarm(ref jawSensorError, value); }
//    [Alarm(true, AlarmLevel.Error, "顶升不在安全位报警", Logical.Equal)]
//    public bool IsAxisSaveAlarm { get => isAxisSaveAlarm; set => NotifyAlarm(ref isAxisSaveAlarm, value); }
//    [Alarm(true, AlarmLevel.Error, "夹爪位置不正确报警", Logical.Equal)]
//    public bool XOffsetLimitError { get => xOffsetLimitError; set => NotifyAlarm(ref xOffsetLimitError, value); }
//    [Alarm(true, AlarmLevel.Error, "夹爪X轴纠偏量超上限", Logical.Equal)]
//    public bool JawPositionError { get => jawPositionError; set => NotifyAlarm(ref jawPositionError, value); }
//    [Alarm(true, AlarmLevel.Error, "撕膜插补移动超时", Logical.Equal)]
//    public bool SiMoActionTimeout { get => siMoActionTimeout; set => NotifyAlarm(ref siMoActionTimeout, value); }
//    [Alarm(true, AlarmLevel.Error, "供料盘拍照报警", Logical.Equal)]
//    public bool FeedTrayError { get => feedTrayError; set => NotifyAlarm(ref feedTrayError, value); }
//    [Alarm(true, AlarmLevel.Warning, "NG料盘已满", Logical.Equal)]
//    public bool NGTrayError { get => ngTrayError; set => NotifyAlarm(ref ngTrayError, value); }

//    #endregion

//    public Electronic Electronic => Electronic.Default;
//    public int Step
//    {
//        get => Status.Step; set
//        {
//            Status.Step = value;
//            Status.Save();
//        }
//    }
//    public event EventHandler<string> StepsChanged;

//    public SiMoStation(Feeder feeder1, Feeder feeder2)
//    {
//        RetryCount = 0;
//        this.InitalizeAlarms();
//        Feeder1 = feeder1;
//        Feeder2 = feeder2;
//        Feeder1.StepCountChanged += Feeder1_StepCountChanged;
//        Feeder2.StepCountChanged += Feeder2_StepCountChanged;
//        LogGroup = LoggerCategory.RunningInfo;
//        DingSheng_Axis = new DmcAxis(Electronic.Controller) { Id = "SiMo" + nameof(DingSheng_Axis), NoId = 31, Name = "撕膜顶升步进" };
//        Jaw1_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw1_Axis), NoId = 22, Name = "撕膜夹爪1步进" };
//        Jaw2_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw2_Axis), NoId = 23, Name = "撕膜夹爪2步进" };
//        Jaw3_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw3_Axis), NoId = 24, Name = "撕膜夹爪3步进" };
//        Jaw4_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw4_Axis), NoId = 25, Name = "撕膜夹爪4步进" };
//        Jaw5_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw5_Axis), NoId = 26, Name = "撕膜夹爪5步进" };
//        Jaw6_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw6_Axis), NoId = 27, Name = "撕膜夹爪6步进" };
//        Jaw7_Axis = new DmcAxis(Electronic.Controller) { Id = nameof(Jaw7_Axis), NoId = 28, Name = "撕膜夹爪7步进" };
//        Add(DingSheng_Axis);
//        Add(Jaw1_Axis, Jaw2_Axis, Jaw3_Axis, Jaw4_Axis, Jaw5_Axis, Jaw6_Axis, Jaw7_Axis);
//        Add(Feeder1.Axis, Feeder2.Axis);
//        Add(Jaw1_Cylinder, Jaw2_Cylinder, Jaw3_Cylinder, Jaw4_Cylinder, Jaw5_Cylinder, Jaw6_Cylinder, Jaw7_Cylinder);
//    }

//    protected override async Task RunningCoreAsync()
//    {
//        try
//        {
//            await GetSiMoPosition(0);
//            await DingShen(1);
//            await WaitBanYunCompleted(2);
//            await JiaMoAction(3);
//            await SiMoAction(4);
//            await PaoMoAction(5);
//        }
//        catch (Exception ex)
//        {
//            throw;
//        }
//    }

//    public async Task<bool> InitializeStation(CancellationToken cancellationToken)
//    {
//        try
//        {
//            LogInfo("开始初始化...");
//            OnStepChanged("初始化中");
//            YaMo1_Cylinder.TakeBack();//张开
//            YaMo2_Cylinder.TakeBack();//张开
//            var axies = this.Automatics.Where(x => x is DmcAxis).Cast<DmcAxis>().ToArray();
//            axies.ForEach(x => x.Reset());
//            axies.ForEach(x => x.ServoOn(true));
//            LogInfo("夹爪闭合");
//            await Parallel.ForEachAsync(Cylinders, cancellationToken, async (x, t) => await x.TakeBackAsync());
//            LogInfo("顶升轴回原点...");
//            await DingSheng_Axis.MoveOriginAsync(cancellationToken);
//            LogInfo("顶升轴到安全位置");
//            await DingSheng_Axis.MoveToAsync(Ds_安全位, cancellationToken);
//            LogInfo("撕膜夹爪轴回原点");
//            await Parallel.ForEachAsync(JawAxises, cancellationToken, async (x, t) => await x.MoveOriginAsync(t));
//            LogInfo("撕膜夹爪轴到安全位置");
//            await JawAxises.MoveToAsync(Jaw_安全位, cancellationToken);

//            if (Status.HasProducts.Any(x => x))
//            {
//                Step = 0;
//            }
//            else
//            {
//                Step = 0;
//            }
//            LogInfo("初始化完成...");
//            OnStepChanged("初始化完成");
//            _isInit = true;
//            return true;

//        }
//        catch (Exception ex)
//        {
//            LogError(ex.Message);
//            return false;
//        }
//    }

//    /// <summary>
//    /// 获取撕膜位置
//    /// </summary>
//    /// <returns></returns>
//    public async Task GetSiMoPosition(int step)
//    {
//        if (Step != step) return;
//        #region TODO:没有启作用
//        //if (_inspectorOption.IsFeiDa1StationShield && _inspectorOption.IsFeiDa2StationShield)
//        //{
//        //    SignalPanel.Signal.IsUseSiMo1 = false;
//        //    SignalPanel.Signal.SiMoReady = true;
//        //    LogInfo("飞达2已经就绪");
//        //}
//        #endregion
//        OnStepChanged("等待飞达就绪");
//        LogInfo("等待飞达是否就绪");
//        await Judger.Sure(() => FeiDaStation1.CheckIsReady() || FeiDaStation2.CheckIsReady(), CancellationToken, interval: 200);
//        if (FeiDaStation1.CheckIsReady())
//        {
//            SignalPanel.Signal.IsUseSiMo1 = true;
//            SignalPanel.Signal.SiMoReady = true;
//            LogInfo("飞达1已经就绪");
//        }
//        else
//        {
//            SignalPanel.Signal.IsUseSiMo1 = false;
//            SignalPanel.Signal.SiMoReady = true;
//            LogInfo("飞达2已经就绪");
//        }
//        SignalPanel.Signal.FeedrReadyDone = true;
//        await Judger.Sure(() => SignalPanel.Signal.FeedrNotReady == false);
//        SignalPanel.Signal.FeedrReadyDone = false;
//        LogInfo($"开始夹爪移动到夹膜等待位.");
//        string ps = SignalPanel.Signal.IsUseSiMo1 ? Jaw_夹膜等待位1 : Jaw_夹膜等待位2;
//        await JawAxises.MoveToAsync(ps, CancellationToken);
//        LogInfo($"完成夹爪移动到夹膜等待位完成");
//        Step = step + 1;
//    }

//    public async Task DingShen(int step)
//    {
//        if (Step != step) return;
//        OnStepChanged("顶升到夹膜位");
//        await DingSheng_Axis.MoveToAsync(Ds_夹膜位, CancellationToken);
//        Step = step + 1;
//    }

//    public async Task WaitBanYunCompleted(int step)
//    {
//        if (Step != step) return;
//        OnStepChanged("等待搬运到位");
//        LogInfo("等待搬运模组到位信号...");
//        await Judger.Sure(() => SignalPanel.Signal.BanYunCompleted || SignalPanel.Signal.FeedrNotReady, CancellationToken);
//        if (SignalPanel.Signal.FeedrNotReady)
//        {
//            Step = 0;//跳回之前第0步重新确认是用那个飞达功能
//            return;
//        }
//        Step = step + 1;
//    }

//    /// <summary>
//    /// 顶升步进顶升,夹爪打开
//    /// </summary>
//    /// <param name="step"></param>
//    /// <returns></returns>
//    public async Task JiaMoAction(int step)
//    {
//        if (Step != step) return;
//        OnStepChanged("夹膜动作");
//        LogInfo($"开始顶升上升夹爪打开");
//        await DingSheng_Axis.MoveToAsync(Ds_夹膜位, CancellationToken);
//        foreach (var item in Cylinders)
//        {
//            item.PushOut();
//        }
//        await Task.Delay(200);
//        LogInfo($"夹爪已打开，夹爪伺服移动到夹膜位");
//        string position = SignalPanel.Signal.IsUseSiMo1 ? Jaw_夹膜位1 : Jaw_夹膜位2;
//        double tolerance = 5;
//        if (SignalPanel.Signal.JawOffsets.Any(x => Math.Abs(x) > tolerance))
//        {
//            LogError($"夹爪X轴纠偏量超上限:{tolerance}！");
//            XOffsetLimitError = true;
//            await Task.Delay(1000);
//            return;
//        }
//        var p1 = Jaw1_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[0];
//        var p2 = Jaw2_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[1];
//        var p3 = Jaw3_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[2];
//        var p4 = Jaw4_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[3];
//        var p5 = Jaw5_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[4];
//        var p6 = Jaw6_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[5];
//        var p7 = Jaw7_Axis.GetTargetPosition(position) + SignalPanel.Signal.JawOffsets[6];
//        var speed1 = Jaw1_Axis.GetVelocityCurve(position);
//        var speed2 = Jaw2_Axis.GetVelocityCurve(position);
//        var speed3 = Jaw3_Axis.GetVelocityCurve(position);
//        var speed4 = Jaw4_Axis.GetVelocityCurve(position);
//        var speed5 = Jaw5_Axis.GetVelocityCurve(position);
//        var speed6 = Jaw6_Axis.GetVelocityCurve(position);
//        var speed7 = Jaw7_Axis.GetVelocityCurve(position);

//        await Parallel.ForEachAsync([(Jaw1_Axis, p1, speed1), (Jaw2_Axis, p2, speed2), (Jaw3_Axis, p3, speed3), (Jaw4_Axis, p4, speed4), (Jaw5_Axis, p5, speed5), (Jaw6_Axis, p6, speed6), (Jaw7_Axis, p7, speed7)], CancellationToken, async (x, t) => await x.Item1.MoveToAsync(x.Item2, x.Item3, t));
//        await Task.Delay(100);
//        LogInfo($"夹爪伺服已到夹膜位，夹爪闭合");
//        foreach (var item in Cylinders)
//        {
//            item.TakeBack();
//        }
//        await Task.Delay(500);
//        var sensor2 = SignalPanel.Signal.IsUseSiMo1 ? Electronic.DI79_夹爪闭合光纤1 : Electronic.DI81_夹爪闭合光纤2;
//        if (!_inspectorOption.IsJawOpenCloseGuangXianShield)
//        {
//            if (!await Judger.Sure(() => sensor2.Value, CancellationToken, 3000))
//            {
//                JawSensorError = true;
//                await Task.Delay(500);
//                return;
//            }
//        }
//        LogInfo($"夹爪已闭合");
//        Step = step + 1;
//    }

//    /// <summary>
//    /// 撕膜动作,顶升轴和夹爪轴直线插补到撕膜位
//    /// </summary>
//    /// <param name="step"></param>
//    /// <returns></returns>
//    public async Task SiMoAction(int step)
//    {
//        if (Step != step) return;
//        OnStepChanged("撕膜动作");
//        LogInfo($"开始撕膜动作（直线插补）");
//        ushort[] axisId = [(ushort)DingSheng_Axis.NoId, (ushort)Jaw1_Axis.NoId, (ushort)Jaw2_Axis.NoId, (ushort)Jaw3_Axis.NoId, (ushort)Jaw4_Axis.NoId, (ushort)Jaw5_Axis.NoId, (ushort)Jaw6_Axis.NoId, (ushort)Jaw7_Axis.NoId];

//        ushort[] axisId2 = [(ushort)Jaw1_Axis.NoId, (ushort)Jaw2_Axis.NoId, (ushort)Jaw3_Axis.NoId, (ushort)Jaw4_Axis.NoId, (ushort)Jaw5_Axis.NoId, (ushort)Jaw6_Axis.NoId, (ushort)Jaw7_Axis.NoId];

//        string endPosition = SignalPanel.Signal.IsUseSiMo1 ? Jaw_撕膜结束位1 : Jaw_撕膜结束位2;
//        string guoduPosition = SignalPanel.Signal.IsUseSiMo1 ? Jaw_撕膜过渡位1 : Jaw_撕膜过渡位2;
//        double[] guodupositions = [DingSheng_Axis.GetTargetPosition(Ds_撕膜过渡位), .. JawAxises.Select(x => x.GetTargetPosition(guoduPosition))];
//        double[] endPositions = [.. JawAxises.Select(x => x.GetTargetPosition(endPosition))];
//        //var siMoSpeed = DingSheng_Axis.GetVelocityCurve(Ds_撕膜结束位);
//        VelocityCurve siMoVelocityCurve = new VelocityCurve() { Maxvel = _inspectorOption.SiMoSpeed, Tdec = 0.1, Tacc = 0.1 };
//        LogInfo("撕膜动作过渡位开始");
//        Electronic.Controller.AbsoluteMove(0, axisId, guodupositions, siMoVelocityCurve);
//        await Judger.Sure(() => Electronic.Controller.IsDone(0), CancellationToken);
//        LogInfo("撕膜动作过渡位已完成,X轴移动到撕膜结束位开始");
//        Electronic.Controller.AbsoluteMove(0, axisId2, endPositions, siMoVelocityCurve);
//        await Judger.Sure(() => Electronic.Controller.IsDone(0), CancellationToken);
//        LogInfo("撕膜动作X轴移动到撕膜结束位完成,Z轴移动结束位开始");
//        await DingSheng_Axis.MoveToAsync(DingSheng_Axis.GetTargetPosition(Ds_撕膜结束位), siMoVelocityCurve, CancellationToken);
//        LogInfo("撕膜动作Z轴移动结束位完成");
//        await Task.Delay(100);
//        LogInfo("撕膜动作完成");
//        Status.HasProducts = [true, true, true, true, true, true, true];
//        SignalPanel.Signal.SiMoCompleted = true;
//        Step = step + 1;


//        //if (Step != step) return;
//        //OnStepChanged("撕膜动作");
//        //LogInfo($"开始撕膜动作（直线插补）");
//        //ushort[] axisId = [(ushort)DingSheng_Axis.NoId, (ushort)Jaw1_Axis.NoId, (ushort)Jaw2_Axis.NoId, (ushort)Jaw3_Axis.NoId, (ushort)Jaw4_Axis.NoId, (ushort)Jaw5_Axis.NoId, (ushort)Jaw6_Axis.NoId, (ushort)Jaw7_Axis.NoId];

//        //string endPosition = SignalPanel.Signal.IsUseSiMo1 ? Jaw_撕膜结束位1 : Jaw_撕膜结束位2;
//        //double[] positions = [DingSheng_Axis.GetTargetPosition(Ds_撕膜结束位), .. JawAxises.Select(x => x.GetTargetPosition(endPosition))];
//        //var siMoSpeed = DingSheng_Axis.GetVelocityCurve(Ds_撕膜结束位);

//        //Electronic.Controller.AbsoluteMove(0, axisId, positions, new VelocityCurve() { Maxvel = _inspectorOption.SiMoSpeed, Tdec = 0.1, Tacc = 0.1 });
//        //await Judger.Sure(() => Electronic.Controller.IsDone(0), CancellationToken);
//        //LogInfo("撕膜动作已完成");
//        //await Task.Delay(100);
//        //Status.HasProducts = [true, true, true, true, true, true, true];
//        //SignalPanel.Signal.SiMoCompleted = true;
//        //Step = step + 1;
//    }

//    /// <summary>
//    /// 顶升下降到压膜位,压膜气缸下压,夹爪张开,夹爪步进退出到安全位
//    /// </summary>
//    /// <param name="step"></param>
//    /// <returns></returns>
//    public async Task PaoMoAction(int step)
//    {
//        if (Step != step) return;
//        OnStepChanged("抛膜动作");
//        LogInfo($"顶升步进到抛膜上位");
//        string ps = SignalPanel.Signal.IsUseSiMo1 ? Ds_抛膜上1 : Ds_抛膜上2;
//        await DingSheng_Axis.MoveToAsync(ps, CancellationToken);
//        var cylinder = SignalPanel.Signal.IsUseSiMo1 ? YaMo1_Cylinder : YaMo2_Cylinder;
//        LogInfo($"顶升步进已到抛膜上,压膜气缸打开");
//        cylinder.TakeBack();//张开
//        await Task.Delay(100);
//        var judgerfeeder = SignalPanel.Signal.IsUseSiMo1 ? Feeder1 : Feeder2;
//        LogInfo($"判断飞达是否运动指令执行完成");
//        await Judger.Sure(() => judgerfeeder.Axis.IsDone, CancellationToken);
//        await judgerfeeder.NianMo2(_inspectorOption.FeedarOneStepDistance, _inspectorOption.FeedarLongStepDistance, _inspectorOption.FeedarSteps, CancellationToken, true);
//        await Judger.Sure(() => judgerfeeder.Axis.IsDone, CancellationToken);
//        LogInfo($"飞达运动执行已经完成");
//        //if (!judgerfeeder.CheckIsReady())
//        //{
//        //    judgerfeeder.ReadyError = true;
//        //    LogError($"{judgerfeeder.Name}未就绪");
//        //    await Task.Delay(2000);
//        //    return;
//        //}
//        string jps = SignalPanel.Signal.IsUseSiMo1 ? Jaw_抛膜位1 : Jaw_抛膜位2;
//        LogInfo($"压膜气缸已打开，开始夹爪步进到抛膜位");
//        await JawAxises.MoveToAsync(jps, CancellationToken);
//        LogInfo($"夹爪步进已到抛膜位，顶升步进到抛膜下");
//        string ps2 = SignalPanel.Signal.IsUseSiMo1 ? Ds_抛膜下1 : Ds_抛膜下2;
//        await DingSheng_Axis.MoveToAsync(ps2, CancellationToken);
//        LogInfo($"顶升步进已到抛膜下,压膜气缸闭合");
//        cylinder.PushOut();//闭合
//        await Task.Delay(100);
//        LogInfo($"压膜气缸已闭合，夹爪打开");
//        foreach (var item in Cylinders)
//        {
//            item.PushOut();
//        }
//        await Task.Delay(200);
//        var sensor1 = SignalPanel.Signal.IsUseSiMo1 ? Electronic.DI80_夹爪张开光纤1 : Electronic.DI82_夹爪张开光纤2;
//        if (!_inspectorOption.IsJawOpenCloseGuangXianShield)
//        {
//            if (!await Judger.Sure(() => sensor1.Value, CancellationToken, 3000, 200))
//            {
//                JawSensorError = true;
//                await Task.Delay(500);
//                return;
//            }
//        }
//        LogInfo($"夹爪已打开，飞达开始粘膜");
//        var feeder = SignalPanel.Signal.IsUseSiMo1 ? Feeder1 : Feeder2;
//        //_ = feeder.NianMo(_inspectorOption.FeedarOneStepDistance, _inspectorOption.FeedarLongStepDistance, _inspectorOption.FeedarSteps, CancellationToken);
//        _ = feeder.NianMo2(_inspectorOption.FeedarOneStepDistance, _inspectorOption.FeedarLongStepDistance, _inspectorOption.FeedarSteps, CancellationToken, false);
//        if (SignalPanel.Signal.IsUseSiMo1)
//            Status.Feeder1Step++;
//        else
//            Status.Feeder2Step++;
//        LogInfo($"夹爪已打开，夹爪步进开始到夹膜等待位");
//        string ps3 = SignalPanel.Signal.IsUseSiMo1 ? Jaw_夹膜等待位1 : Jaw_夹膜等待位2;
//        await JawAxises.MoveToAsync(ps3, CancellationToken);
//        LogInfo($"夹爪步进已到等待位，完成抛膜动作");
//        if (!_inspectorOption.IsJawGuangXianShield)
//        {
//            var sensors = SignalPanel.Signal.IsUseSiMo1 ? JawSensors1 : JawSensors2;
//            var selectedSensor = Functions.SelectObjects(sensors.ToList(), BanYunStation.Status.NozzleStatus.Select(x => x != TrayPointStatus.Empty || x != TrayPointStatus.NG).ToList());
//            if (await Judger.Sure(() => selectedSensor.Any(x => x.Value), CancellationToken))
//            {
//                JawSensorError = true;
//                await Task.Delay(500);
//                return;
//            }
//        }
//        Status.HasProducts = [false, false, false, false, false, false, false];
//        Step = 0;
//    }

//    private void Feeder1_StepCountChanged(object? sender, int e)
//    {
//        Status.Feeder1Step = e;
//    }

//    private void Feeder2_StepCountChanged(object? sender, int e)
//    {
//        Status.Feeder2Step = e;
//    }

//    public void ClearAlarm()
//    {
//        JawSensorError = false;
//        IsAxisSaveAlarm = false;
//        JawPositionError = false;
//        SiMoActionTimeout = false;
//        NGTrayError = false;
//        XOffsetLimitError = false;
//    }

//    public void OnStepChanged(string step)
//    {
//        StepsChanged?.SafeInvoke(this, step);
//    }

//    protected override async void OnStopped()
//    {
//        var axies = this.Automatics.Where(x => x is DmcAxis).Cast<DmcAxis>().ToArray();
//        await Parallel.ForEachAsync(axies, cancellationToken: default, async (x, t) => await x.PauseAsync());
//        Status.JaxAxisesPositions = JawAxises.Select(x => x.Current).ToArray();
//        Status.Save();
//    }

//    protected override async Task PreRunning()
//    {
//        try
//        {
//            foreach (var automatic in Automatics)
//            {
//                if (automatic is DmcAxis dmcAxis)
//                {
//                    await dmcAxis.InitializeAsync();
//                }
//            }
//            Status = RunningStatus.GetRecord<SiMoRunniningStatus>("SiMoStation.json");
//            var repository = Service.GetRequiredService<IOptionRepository>();
//            _inspectorOption = repository.Get<InspectorOption>();
//            var recipe = Service.GetRequiredService<ICurrentRecipe>();
//            Option = recipe.Get<SiMoStationOption>(Id);
//            if (!_isInit)
//            {
//                _isInit = await InitializeStation(CancellationToken);
//            }
//            else
//            {
//                for (int i = 0; i < JawAxises.Count; i++)
//                {
//                    if (Math.Abs(JawAxises[i].Current - Status.JaxAxisesPositions[i]) > 1)
//                    {
//                        await JawAxises[i].MoveToAsync(Jaw_安全位, CancellationToken);
//                    }
//                }
//            }
//        }
//        catch (Exception exception)
//        {
//            LogError(exception);
//            Root.Stop();
//        }
//    }

//    public override async Task InitializeAsync()
//    {
//        Status = RunningStatus.GetRecord<SiMoRunniningStatus>("SiMoStation.json");
//        Feeder1.Count = Status.Feeder1Step;
//        Feeder2.Count = Status.Feeder2Step;
//        var repository = Service.GetRequiredService<IOptionRepository>();
//        _inspectorOption = repository.Get<InspectorOption>();
//        await base.InitializeAsync();
//    }
//}
#endregion

